class Solution {
private HashMap<Integer, CacheNode> map;
private int capacity;
private CacheNode head = new CacheNode(-1, -1);
private CacheNode tail = new CacheNode(-1, -1);
private class CacheNode {
int key, value;
CacheNode pre, next;
CacheNode(int key, int value) {
this.key = key;
this.value = value;
this.pre = null;
this.next = null;
}
public Solution(int capacity) {
this.capacity = capacity;
this.map = new HashMap<>();
}
private void moveToTail(CacheNode target, boolean isNew) {
if (target != tail.next) {
if (!isNew) {
target.pre.next = target.next;
target.next.pre = target.pre;
}
tail.next.next = target;
target.pre = tail.next;
tail.next = target;
}
}
public int get(int key) {
if (map.containsKey(key)) {
CacheNode target = map.get(key);
moveToTail(target, false);
tail.next.next = null;
return target.value;
}
return -1;
}
public void set(int key, int value) {
if (map.containsKey(key)) {
CacheNode target = map.get(key);
target.value = value;
map.put(key, target);
moveToTail(target, false);
} else if (map.size() < capacity) {
CacheNode newNode = new CacheNode(key, value);
map.put(key, newNode);
if (head.next == null) {
head.next = newNode;
newNode.pre = head;
tail.next = newNode;
} else {
moveToTail(newNode, true);
}
} else {
CacheNode newNode = new CacheNode(key, value);
map.remove(head.next.key);
map.put(key, newNode);
if (head.next == tail.next) {
head.next = newNode;
tail.next = newNode;
} else {
head.next.next.pre = head;
head.next = head.next.next;
moveToTail(newNode, true);
}
}
}
}
}